﻿#!/usr/bin/env python3
#! -*- encoding: utf-8 -*-	

#4 函数式编程

def traceArr(name,arr):
	print("数组名：",name,(isinstance(arr,list)),",的值是 :")
	for x in arr:
		print(x)

#1).高阶函数

#编写高阶函数，就是让函数的参数能够接收别的函数。

def add(x,y,f):
	return f(x)+f(y)

print(add(-5,6,abs))

#2).map/reduce 函数的使用

#map函数
def f(x):
 return x*x
 
itor = map(f,[1,2,3,4,5]) #返回的是一个迭代器
print(itor)
arr1 = list(itor)
print(arr1[0])
traceArr("arr1",arr1)

#把list的元素全部转换成字符串str
arr2=map(str,[10,20,30,40])
arr2 = list(arr2)
traceArr("arr2",arr2) 

#reduce函数
from functools import reduce
def fn(x1,x2):
	return x1+x2;

#得到数组内元素的和 主要是做累积运算,fn第一次接收的是list[0],list[1] 第二次接收的是 list[0]+list[1]的和和list[2] 以此类推	
sumVal = reduce(fn,[1,3,5,7]) 
print("sumVal=",sumVal)	
	
#filter函数
def is_odd(n):
	return n%2==0;
	
arr3 = list(filter(is_odd,[1,2,3,4,5,6,7,8,9,10]))#只保留is_odd中返回True的元素 ,该函数主要是用于筛选的作用

traceArr("arr3",arr3)

#判断是否是回数
def isReNum(num):
	s = str(num)
	le = len(s)//2 #强制得到向下取整
	for i in range(le):  
		if s[i] != s[len(s)-i-1]:
			return False		
	return True	
print("isReNum=",isReNum(909))
	
#排序算法 sorted函数

arr4 = [10,2,50,-40,-5,45,8];
#排序后返回的新的list不改变原list,默认升序
arr4 = sorted(arr4) 
traceArr("arr4",arr4)

arr5 = ["Zoom","boy","about","feed"];

arr5 = sorted(arr5) #按照ascii码排序
traceArr("arr5",arr5)

#按照ascii码排序,reverse反向排序,也就是变成降序了
arr5 = sorted(arr5,key=str.lower,reverse=True) 
traceArr("arr5",arr5)
#指定根据list元素中的某个值排序
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
print(L)
L = sorted(L,key=lambda t:t[0]) #根据L中每个tuple的第一个元素排序
print(L)


def count():
	fs = [1,2,3]
	return fs
	
n1,n2,n3=count(); #这样可以把函数返回的list逐一赋值给三个变量
print(n1,n2,n3)
	
#闭包

def closureFc():
	fs = [];
	for i in range(1,4):
		def f():
			return i*i;
		fs.append(f)
	return fs

f1,f2,f3=closureFc()
print(f1()) # 9
print(f2()) # 9
print(f3()) # 9
#为什么上面三个函数执行结果都是9呢？
#因为闭包函数内保存的i在循环执行完成后已经发生改变,变成3,所以闭包返回的函数里面的变量i的值是3 所以得到的结果就是i*i=9
#返回闭包时牢记的一点就是：返回函数不要引用任何循环变量，或者后续会发生变化的变量。

#匿名函数
#匿名函数有个限制，就是只能有一个表达式，不用写return，返回值就是该表达式的结果。
#定义匿名函数:
f = lambda x,y:x*x+y
print(f(5,10))

#装饰器


#获取函数的函数名
import functools
def dec_f():
	pass;

print(dec_f.__name__) #任何函数的__name__属性就会得到函数名

#定义一个装饰器:装饰器其实就是一个接受函数作为参数的高阶函数
#定义个打印调用函数的装饰器函数
def log(func):
	@functools.wraps(func) #防止改变函数的函数名
	def wrapper(*args,**kw):
		print("call %s:"%func.__name__)
		return func(*args,**kw)
	return wrapper

#运行装饰器的语法,@然后加函数名称
@log  #相当于 log(now)
def now():
	print("2016-3-10 12:01:10")
now()
print(now.__name__) 

#偏函数
import functools

int2 = functools.partial(int,base=2) # 得到int2函数是一个把二进制转换成10进制的函数

print(int2("1001")) #必须传入二进制数



	